package com.itheima.tanhua.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.itheima.tanhua.api.MovementApi;
import com.itheima.tanhua.api.UserInfoApi;
import com.itheima.tanhua.api.VisitorsApi;
import com.itheima.tanhua.autoconfig.template.OssTemplate;
import com.itheima.tanhua.domain.UserInfo;
import com.itheima.tanhua.dto.UserFreezeDto;
import com.itheima.tanhua.enums.LogType;
import com.itheima.tanhua.exception.BusinessException;
import com.itheima.tanhua.mongo.Movement;
import com.itheima.tanhua.mongo.Visitors;
import com.itheima.tanhua.utils.Constants;
import com.itheima.tanhua.utils.UserHolder;
import com.itheima.tanhua.vo.*;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Lff
 * @date 2022/3/26
 */
@Service
public class MovementService {

    @Autowired
    private OssTemplate oss;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private UserFreezeService userFreezeService;
    @Autowired
    private RedisTemplate redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    @Autowired
    private MqMessageService mqMessageService;

    /**
     * 发布动态
     *
     * @param movement
     * @param imageContent
     */
    public void publisher(Movement movement, MultipartFile[] imageContent) {
        //检查用户状态
        userFreezeService.checkUserStatus("3", UserHolder.getUser().getId());
        //检查正文是否为null
        if (StringUtils.isEmpty(movement.getTextContent())) {
            //没有动态正文 抛出异常
            throw new BusinessException(ErrorResult.contentError());
        }
        //上传图片到阿里云
        List<String> medias = new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            try {
                String fileUrl = oss.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                //保存到集合当中
                medias.add(fileUrl);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //填充movement的userId，media
        movement.setUserId(UserHolder.getUser().getId());
        movement.setMedias(medias);
        //调用Api实现保存
        String publisherId = movementApi.publisher(movement);
        try {
            //调用mq发送消息
            mqMessageService.sendAudiService(publisherId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取指定用户所有动态
     * userId为null时，则获取当前登录用户的所有动态
     *
     * @param userId
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult getAllMovement(Long userId, Integer page, Integer pagesize) {
        //如果userId为null则获取当前登陆用户的id
        userId = userId == null ? UserHolder.getUser().getId() : userId;
        //查询mongo从mongo中获取用户的所有动态
        PageResult pr = movementApi.getMovementsByUserId(userId, page, pagesize);
        //获取items
        List<Movement> items = (List<Movement>) pr.getItems();
        //该用户没有发动态，不进行后面的操作，直接返回
        if (pr.getItems() == null) {
            return pr;
        }
        //有动态
        //查询该用户的信息
        UserInfo userInfo = userInfoApi.findById(userId);
        //遍历填充MovementVo
        List<MovementsVo> results = items.stream().map(movement -> {
            MovementsVo init = MovementsVo.init(userInfo, movement);
            return init;
        }).collect(Collectors.toList());
        //将新的items添加到pr中
        pr.setItems(results);
        //返回数据
        return pr;
    }

    /**
     * 查询当前登录用户的所有可见的好友动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findFriendMovements(Integer page, Integer pagesize) {
        //获取用户id
        Long id = UserHolder.getUser().getId();
        //调用Api查询当前好友的动态
        List<Movement> movements = movementApi.findFriendMovements(page, pagesize, id);
        return getPageResult(page, pagesize, movements);
    }


    /**
     * 获取推荐动态
     * 查询缓存中的pid 有 ==>根据pid去查询推荐动态
     * 没有pid 随机生成动态
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult findRecommendMovements(Integer page, Integer pagesize) {
        //构造缓存中的键
        String key = Constants.MOVEMENTS_RECOMMEND + UserHolder.getUser().getId();
        //获取缓存中的pid
        String pidStr = (String) redisTemplate.opsForValue().get(key);
        //构建结果集合
        List<Movement> movements = Collections.EMPTY_LIST;
        //判断是否为null
        if (StringUtils.isEmpty(pidStr)) {
            //为null随机生成动态数据
            movements = movementApi.randomRecommendMovements(pagesize);
        } else {
            //不为null通过pid查询动态
            //提取pid
            String[] pids = pidStr.split(",");
            if ((page - 1) * pagesize < pids.length) {
                List<Long> pidList = Arrays.stream(pids).skip((page - 1) * pagesize).limit(pagesize)
                        .map(r -> Convert.toLong(r)).collect(Collectors.toList());
                //调用api查询
                movements = movementApi.findRecommendMovements(pidList);
            }
        }
        //获取到动态后查询UserInfo获取用户详情信息
        //构造返回值
        PageResult pageResult = getPageResult(page, pagesize, movements);
        //返回
        return pageResult;
    }

    /**
     * 封装返回对象
     *
     * @param page
     * @param pagesize
     * @param movements
     * @return
     */
    private PageResult getPageResult(Integer page, Integer pagesize, List<Movement> movements) {
        if (CollUtil.isEmpty(movements)) {
            return new PageResult();
        }
        //抽取动态中的好友id
        List<Long> ids = CollUtil.getFieldValues(movements, "userId", Long.class);
        //通过调用api通过id集合查询用户的详细信息 userInfo
        Map<Long, UserInfo> map = userInfoApi.getUserInfosToMap(ids, null);
        //拿到当前登录用户的id
        Long id = UserHolder.getUser().getId();
        //封装对象
        List<MovementsVo> results = movements.stream().map(m -> {
                    MovementsVo movementsVo = MovementsVo.init(map.get(m.getUserId()), m);
                    //查询缓存判断此条记录是否被当前用户点赞
                    //构建key&hashKey
                    String key = Constants.MOVEMENTS_INTERACT_KEY + m.getId();
                    String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + id;
                    if (redisTemplate.opsForHash().hasKey(key, hashKey)) {
                        movementsVo.setHasLiked(1);
                    }
                    String hashKey1 = Constants.MOVEMENT_LOVE_HASHKEY + id;
                    if (redisTemplate.opsForHash().hasKey(key, hashKey1)) {
                        movementsVo.setHasLoved(1);
                    }
                    return movementsVo;
                }
        ).collect(Collectors.toList());
        //返回数据
        PageResult pageResult = new PageResult(page, pagesize, 0l, results);
        return pageResult;
    }

    /**
     * 根据动态id获取指定动态
     *
     * @param movementId
     * @return
     */
    public MovementsVo findMovementOne(String movementId) {
        //获取动态信息
        Movement movement = movementApi.findOneById(movementId);
        //获取此动态所属用户的用户信息
        UserInfo userInfo = userInfoApi.findById(movement.getUserId());
        return MovementsVo.init(userInfo, movement);
    }


    /**
     * 查询访客记录
     *
     * @return
     */
    public List<VisitorsVo> findVisitors() {
        //获取当前登陆用户的id
        Long id = UserHolder.getUser().getId();
        //存储查询时间
        String key = Constants.VISITORS;
        String hashKey = id.toString();
        String dateStr = (String) redisTemplate.opsForHash().get(key, hashKey);
        Long date = StringUtils.isEmpty(dateStr) ? null : Long.valueOf(dateStr);
        //调用Api获取访客记录并返回
        List<Visitors> list = visitorsApi.findMyVisitors(id, date);
        if (CollUtil.isEmpty(list)) {
            return null;
        }
        List<Long> userIds = CollUtil.getFieldValues(list, "visitorUserId", Long.class);

        //调用userInfoApi查询用户信息
        Map<Long, UserInfo> userMap = userInfoApi.getUserInfosToMap(userIds, null);

        List<VisitorsVo> results = new ArrayList();
        list.stream().forEach(visitors -> {
            UserInfo userInfo = userMap.get(visitors.getVisitorUserId());
            if (userInfo != null) {
                VisitorsVo init = VisitorsVo.init(userInfo, visitors);
                results.add(init);
            }
        });
        return results;
    }
}
